package com.heima.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.heima.apis.apuser.IApUserClient;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.pojos.ApCommentVo;
import com.heima.comment.service.CommentService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.UpdateArticleInfo;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.ApUserThreadLocalUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

/**
 * @author HNCheng
 * @version 1.0
 * @since 2023/8/3 10:21
 */
@Service
public class CommentServiceImpl implements CommentService {

    //评论展示条数 10
    private final static int SIZE = 10;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private IArticleClient articleClient;

    @Autowired
    private IApUserClient apUserClient;

    @Autowired
    private IWemediaClient wemediaClient;

    @Autowired
    private KafkaTemplate kafkaTemplate;

    /**
     * 保存评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1.校验参数
        if (dto == null || StringUtils.isBlank(dto.getContent()) || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.判断用户是否登录
        ApUser apUser = ApUserThreadLocalUtil.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.判断当前文章是否可以评论
        boolean flag = checkArticleComment(dto.getArticleId());
        if (!flag) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //4.判断评论内容字数是否超过140
        if (dto.getContent().length() > 140) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //5.检测评论内容是否为垃圾文本
        Map<String, String> resultMap = wemediaClient.scanText(dto.getContent());
        String conclusionType = resultMap.get("conclusionType");
        if (!"1".equals(conclusionType)) {
            //文本审核不通过
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //6.创建评论对象 保存到数据库
        //6.1根据用户id获取用户详情中的用户名
        ApUser user = apUserClient.findUserById(apUser.getId());
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApComment apComment = ApComment.builder()
                .authorId(apUser.getId())
                .authorName(user.getName())
                .entryId(dto.getArticleId())
                .content(dto.getContent())
                .type((short) 0)
                .reply(0)
                .likes(0)
                .flag((short) 0)
                .createdTime(new Date())
                .build();

        mongoTemplate.save(apComment);

        //7.发送消息,更新文章信息
        UpdateArticleInfo updateArticleInfo = new UpdateArticleInfo();
        updateArticleInfo.setArticleId(dto.getArticleId());
        updateArticleInfo.setComment(1);
        kafkaTemplate.send(ArticleConstants.ARTICLE_SCORE_TOPIC, JSON.toJSONString(updateArticleInfo));

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult likeComment(CommentLikeDto dto) {
        //1.校验参数
        if (dto == null || dto.getCommentId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.判断用户是否登录
        ApUser apUser = ApUserThreadLocalUtil.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.根据评论id查询评论
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        //4.点赞
        if (dto.getOperation() != null && dto.getOperation() == 0) {
            //增加点赞数量
            apComment.setLikes(apComment.getLikes() + 1);
            mongoTemplate.save(apComment);

            //保存评论的点赞数据
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(apUser.getId());
            apCommentLike.setCommentId(apComment.getId());
            mongoTemplate.save(apCommentLike);
        } else if (dto.getOperation() != null && dto.getOperation() == 1) {
            //减少点赞数量
            apComment.setLikes(apComment.getLikes() - 1 < 1 ? 0 : apComment.getLikes() - 1);
            mongoTemplate.save(apComment);

            //删除评论点赞
            Query query = Query.query(Criteria.where("commentId").is(apComment.getId()).and("authorId").is(apUser.getId()));
            mongoTemplate.remove(query, ApCommentLike.class);
        }

        //5.封装返回值
        Map<String, Object> result = new HashMap<>();
        result.put("likes", apComment.getLikes());
        return ResponseResult.okResult(result);
    }

    /**
     * 查询评论列表
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult commentList(CommentDto dto) {
        //1.校验参数
        if (dto == null || dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.判断用户是否登录
        ApUser apUser = ApUserThreadLocalUtil.getUser();
        if (apUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //3.加载数据 先按照点赞数降序 再按发布时间降序
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId()).and("createdTime").lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC, "likes")).with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(SIZE);
        List<ApComment> list = mongoTemplate.find(query, ApComment.class);

        //4.查询当前被点赞的评论
        List<String> idList = list.stream().map(apComment -> apComment.getId()).collect(Collectors.toList());
        Query query1 = Query.query(Criteria.where("commentId").in(idList).and("authorId").is(apUser.getId()));
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(query1, ApCommentLike.class);
        if (apCommentLikes == null || apCommentLikes.size() == 0) {
            return ResponseResult.okResult(list);
        }

        //4.1.封装成commentVo对象返回
        List<ApCommentVo> commentVos = new ArrayList<>();
        for (ApComment apComment : list) {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment, apCommentVo);
            for (ApCommentLike apCommentLike : apCommentLikes) {
                //4.2.将当前用户点赞评论赋值Operation
                if (apComment.getId().equals(apCommentLike.getCommentId())) {
                    apCommentVo.setOperation((short) 0);
                }
            }
            commentVos.add(apCommentVo);
        }
        return ResponseResult.okResult(commentVos);
    }

    /**
     * 判断当前文章是否可以评论
     *
     * @param articleId
     * @return
     */
    private boolean checkArticleComment(Long articleId) {

        // 根据文章id获取文章配置
        ResponseResult responseResult = articleClient.findArticleConfigByArticleId(articleId);
        if (!responseResult.getCode().equals(200) || responseResult.getData() == null) {
            return false;
        }

        JSONObject jsonData = JSON.parseObject(JSON.toJSONString(responseResult.getData()));

        return jsonData.getBoolean("isComment");
    }
}
